package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.admin.api.feign.RemoteDeptService;
import com.engine4cloud.tdf.common.core.constant.SecurityConstants;
import com.engine4cloud.tdf.common.core.constant.enums.CorFileTypeEnum;
import com.engine4cloud.tdf.common.core.constant.enums.InvAuditActionStatusEnum;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.R;
import com.engine4cloud.tdf.common.core.util.RetOps;
import com.engine4cloud.tdf.common.data.web.query.Pages;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.common.data.web.response.PageInfo;
import com.engine4cloud.tdf.common.security.service.TdfUser;
import com.engine4cloud.tdf.common.security.util.SecurityUtils;
import com.engine4cloud.tdf.supervision.convert.DcpgInvCrimeNameConvert;
import com.engine4cloud.tdf.supervision.convert.DcpgInvestigationConvert;
import com.engine4cloud.tdf.supervision.dto.DcpgEvaluateDTO;
import com.engine4cloud.tdf.supervision.dto.IdentityUniqueCheckDTO;
import com.engine4cloud.tdf.supervision.dto.InvAuditDTO;
import com.engine4cloud.tdf.supervision.dto.JzdxFileDTO;
import com.engine4cloud.tdf.supervision.dto.create.DcpgAuditCreateDTO;
import com.engine4cloud.tdf.supervision.dto.create.DcpgInvestigationCreateDTO;
import com.engine4cloud.tdf.supervision.dto.query.DcpgEvaluateQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.DcpgInvCrimeNameQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.DcpgInvestigationQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxFileQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.DcpgInvCrimeNameResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.DcpgInvestigationResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.DcpgSurveyResultDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxFileResultDTO;
import com.engine4cloud.tdf.supervision.dto.update.DcpgAuditDepartUpdateDTO;
import com.engine4cloud.tdf.supervision.dto.update.DcpgInvestigationUpdateDTO;
import com.engine4cloud.tdf.supervision.dto.update.DcpgPreActionUpdateDTO;
import com.engine4cloud.tdf.supervision.entity.DcpgInvCrimeNameEntity;
import com.engine4cloud.tdf.supervision.entity.DcpgInvestigationEntity;
import com.engine4cloud.tdf.supervision.mapper.DcpgInvestigationMapper;
import com.engine4cloud.tdf.supervision.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 调查评估信息表
 *
 * @author wenjie
 * @date 2024-02-29 18:04:50
 */
@Service
public class DcpgInvestigationServiceImpl extends ServiceImpl<DcpgInvestigationMapper, DcpgInvestigationEntity> implements DcpgInvestigationService {

    @Resource
    private DcpgInvCrimeNameService crimeNameService;

    @Lazy
    @Resource
    private DcpgSurveyService surveyService;

    @Resource
    private DcpgAuditResultService auditResultService;

    @Resource
    private JzdxFileService fileService;

    @Resource
    private RemoteDeptService remoteDeptService;

    @Override
    public PageInfo<DcpgInvestigationResultDTO> pageList(DcpgInvestigationQueryDTO dto) {
        R<List<Long>> deptIdRemoteList = remoteDeptService.getDescendantIdList(dto.getDeptId(), SecurityConstants.FROM_IN);
        List<Long> deptIdList = RetOps.of(deptIdRemoteList).getData().filter(CollectionUtils::isNotEmpty)
                .orElseThrow(() -> new ValidateCodeException("没有数据权限!"));

        IPage<DcpgInvestigationResultDTO> page = this.baseMapper.pageList(Pages.page(dto), dto, deptIdList);
        page.setRecords(this.preCrimeNameList(page.getRecords()));
        return Pages.convert(page);
    }

    @Override
    public DcpgInvestigationResultDTO getById(Long id) {
        DcpgInvestigationResultDTO investigationResult = Optional.ofNullable(this.baseMapper.detail(id))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        //设置地区列表
        DcpgInvestigationConvert.INSTANCE.renderAreaList(investigationResult);

        //设置犯罪信息
        DcpgInvCrimeNameQueryDTO crimeNameQuery = new DcpgInvCrimeNameQueryDTO(investigationResult.getDcpgbh());
        List<DcpgInvCrimeNameResultDTO> crimeList = crimeNameService.findList(crimeNameQuery);
        if (CollectionUtils.isNotEmpty(crimeList)) {
            investigationResult.setCrimeNameList(crimeList);
        }

        //设置委托调查书
        JzdxFileQueryDTO invQuery = new JzdxFileQueryDTO();
        invQuery.setDcpgbh(investigationResult.getDcpgbh());
        invQuery.setFileType(CorFileTypeEnum.MANDATORY_INV_DOC);
        List<JzdxFileResultDTO> invFileList = fileService.findList(invQuery);
        if (CollectionUtils.isNotEmpty(invFileList)) {
            investigationResult.setInvFileList(invFileList);
        }

        //设置调查事项列表
        DcpgEvaluateQueryDTO evaluateQuery = new DcpgEvaluateQueryDTO(investigationResult.getDcpgbh());
        List<DcpgSurveyResultDTO> surveyList = surveyService.findList(evaluateQuery);
        if (CollectionUtils.isNotEmpty(surveyList)) {
            investigationResult.setSurveyList(surveyList);
        }

        //设置调查评估意见书
        JzdxFileQueryDTO evaluationQuery = new JzdxFileQueryDTO();
        evaluationQuery.setDcpgbh(investigationResult.getDcpgbh());
        evaluationQuery.setFileType(CorFileTypeEnum.SURVEY_EVALUATION_DOC);
        List<JzdxFileResultDTO> evaluationList = fileService.findList(evaluationQuery);
        if (CollectionUtils.isNotEmpty(evaluationList)) {
            investigationResult.setEvaluationList(evaluationList);
        }

        return investigationResult;
    }

    @Override
    public DcpgInvestigationResultDTO getByCode(String code) {
        DcpgInvestigationQueryDTO query = new DcpgInvestigationQueryDTO();
        query.setDcpgbh(code);

        DcpgInvestigationEntity entity = Optional.ofNullable(this.getOne(wrapper(query)))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        return DcpgInvestigationConvert.INSTANCE.convert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean create(DcpgInvestigationCreateDTO dto) {
        Boolean unique = this.checkUniqueByIdentity(new IdentityUniqueCheckDTO(dto.getBgrzjh()));
        if (!unique) {
            throw new ValidateCodeException("证件号已存在");
        }

        TdfUser user = SecurityUtils.getUser();
        //设置调查评估主信息
        DcpgInvestigationEntity entity = DcpgInvestigationConvert.INSTANCE.create(dto, user.getDeptId(), user.getTenantId(), InvAuditActionStatusEnum.CREATE);
        //保存主信息
        save(entity);

        //设置罪名
        List<DcpgInvCrimeNameEntity> crimeNameEntityList = DcpgInvCrimeNameConvert.INSTANCE.convert(entity, dto.getCrimeNameList());
        crimeNameService.saveBatch(crimeNameEntityList);

        //设置委托调查书
        JzdxFileQueryDTO query = new JzdxFileQueryDTO();
        query.setDcpgbh(entity.getDcpgbh());
        query.setFileType(CorFileTypeEnum.MANDATORY_INV_DOC);
        fileService.batchSaveFile(query, dto.getInvFileList(), user);

        //设置状态
        DcpgAuditCreateDTO audit = new DcpgAuditCreateDTO();
        audit.setDcpgbh(entity.getDcpgbh());
        return auditResultService.audit(audit, new InvAuditDTO(user.getDeptId(), InvAuditActionStatusEnum.CREATE));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(DcpgInvestigationUpdateDTO dto) {
        DcpgInvestigationEntity old = Optional.ofNullable(baseMapper.selectById(dto.getId()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        Boolean unique = this.checkUniqueByIdentity(new IdentityUniqueCheckDTO(dto.getId(), dto.getBgrzjh()));
        if (!unique) {
            throw new ValidateCodeException("证件号已存在");
        }

        //保存主体信息
        updateById(DcpgInvestigationConvert.INSTANCE.update(dto));
        //设置委托调查书
        this.batchUpdateFile(dto.getInvFileList(), old, CorFileTypeEnum.MANDATORY_INV_DOC);
        //设置罪名
        return crimeNameService.updateBatch(old, dto.getCrimeNameList());
    }

    /**
     * 结果意见
     *
     * @param dto 调查结果对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean evaluate(DcpgEvaluateDTO dto) {
        DcpgInvestigationResultDTO old = Optional.ofNullable(this.getByCode(dto.getDcpgbh()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        DcpgInvestigationEntity entity = DcpgInvestigationConvert.INSTANCE.convert(old);
        entity.setDcjgsm(dto.getDcjgsm());
        this.saveOrUpdate(entity);

        //设置调查评估意见书
        this.batchUpdateFile(dto.getEvaluationList(), entity, CorFileTypeEnum.SURVEY_EVALUATION_DOC);
        return true;
    }

    @Override
    public void changeAction(DcpgPreActionUpdateDTO dto) {
        DcpgInvestigationEntity entity = Optional.ofNullable(this.getOne(wrapper(new DcpgInvestigationQueryDTO(dto.getDcpgbh()))))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        entity.setPreAction(dto.getAction());
        super.updateById(entity);
    }

    @Override
    public Boolean changeDepart(DcpgAuditDepartUpdateDTO dto, InvAuditActionStatusEnum actionStatus) {
        DcpgInvestigationEntity entity = Optional.ofNullable(this.getOne(wrapper(new DcpgInvestigationQueryDTO(dto.getDcpgbh()))))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        //设置部门属性
        entity.setDeptId(dto.getDeptId());

        if (Objects.equals(InvAuditActionStatusEnum.COUNTRY_ASSIGN, actionStatus)) {
            entity.setDcdwxqj(dto.getDeptId());
        }

        if (Objects.equals(InvAuditActionStatusEnum.VILLAGE_ACCEPT, actionStatus)) {
            entity.setDcdwsfs(dto.getDeptId());
        }

        baseMapper.updateById(entity);
        return true;
    }

    private List<DcpgInvestigationResultDTO> preCrimeNameList(List<DcpgInvestigationResultDTO> recordList) {
        if (CollectionUtils.isEmpty(recordList)) {
            return recordList;
        }

        //设置罪名和委托书（附加信息）列表
        List<String> codeList = recordList.stream().map(DcpgInvestigationResultDTO::getDcpgbh).toList();
        List<DcpgInvCrimeNameResultDTO> invCrimeNameList = crimeNameService.findList(new DcpgInvCrimeNameQueryDTO(codeList));
        List<JzdxFileResultDTO> invFileList = fileService.findList(new JzdxFileQueryDTO(codeList, CorFileTypeEnum.MANDATORY_INV_DOC));
        return recordList.stream().map(record -> DcpgInvestigationConvert.INSTANCE.additionalInfo(record, invCrimeNameList, invFileList)).toList();
    }

    public Boolean checkUniqueByIdentity(IdentityUniqueCheckDTO dto) {
        LambdaQueryWrapper<DcpgInvestigationEntity> wrapper = Queries.lambda();
        Queries.accept(dto.getIdentity(), v -> wrapper.eq(DcpgInvestigationEntity::getBgrzjh, v));
        wrapper.ne(DcpgInvestigationEntity::getPreAction, InvAuditActionStatusEnum.DELIVERY);

        Optional<DcpgInvestigationEntity> optional = Optional.ofNullable(this.getOne(wrapper));
        return optional.map(inv -> Objects.equals(inv.getId(), dto.getId())).orElse(true);
    }

    private void batchUpdateFile(List<JzdxFileDTO> fileList, DcpgInvestigationEntity old, CorFileTypeEnum fileType) {
        JzdxFileQueryDTO query = new JzdxFileQueryDTO();
        query.setDcpgbh(old.getDcpgbh());
        query.setFileType(fileType);
        fileService.batchUpdateFile(query, fileList, SecurityUtils.getUser());
    }

    private LambdaQueryWrapper<DcpgInvestigationEntity> wrapper(DcpgInvestigationQueryDTO query) {
        LambdaQueryWrapper<DcpgInvestigationEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(DcpgInvestigationEntity::getId, v));
        Queries.accept(query.getDcpgbh(), v -> wrapper.eq(DcpgInvestigationEntity::getDcpgbh, v));
        Queries.accept(query.getWtbh(), v -> wrapper.eq(DcpgInvestigationEntity::getWtbh, v));
        Queries.accept(query.getBgrxm(), v -> wrapper.like(DcpgInvestigationEntity::getBgrxm, v));
        Queries.accept(query.getBgrzjh(), v -> wrapper.like(DcpgInvestigationEntity::getBgrzjh, v));
        Queries.accept(query.getNsyjzlb(), v -> wrapper.eq(DcpgInvestigationEntity::getNsyjzlb, v));
        Queries.accept(query.getDcpgjg(), v -> wrapper.eq(DcpgInvestigationEntity::getDcpgjg, v));
        Queries.accept(query.getDeptId(), v -> wrapper.eq(DcpgInvestigationEntity::getDeptId, v));
        return wrapper;
    }
}